﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TlvLib.PacketParsers;

namespace TlvLib
{
    public class NewPacketEventArgs : EventArgs
    {
        public object Packet { get; set; }

        public NewPacketEventArgs(object packet)
        {
            Packet = packet;
        }
    }


    public delegate void NewPacketEventHandler(object sender, NewPacketEventArgs args);

    public class PacketHandler
    {
        private List<IPacketParser> _packetParsers = new List<IPacketParser>();
        private PacketParsers.LpiReplyPacker _lpiReplyPacker =  new LpiReplyPacker(); 
        private TlvUnpacker _tlvUnpacker;
        private Action<string> _logger;

        public event NewPacketEventHandler NewPacketReceived;

        public event StatusReportHandler ReportStatus
        {
            add { _tlvUnpacker.StatusReport += value; }
            remove { _tlvUnpacker.StatusReport -= value; }
        }

        public void RaiseNewPacketReceived(NewPacketEventArgs args)
        {
            NewPacketEventHandler handler = NewPacketReceived;
            if (handler != null) handler(this, args);
        }

        public void SetLogger(Action<string> logger)
        {
            foreach (var packetParser in _packetParsers)
            {
                packetParser.Logger = logger;
            }

            _logger = logger;
        }

        public PacketHandler(string host, int port)
        {
            InitParsers();

            _tlvUnpacker = new TlvUnpacker(host, port);
            _tlvUnpacker.RawPacketReceived += _tlvUnpacker_RawPacketReceived;
        }

        private void InitParsers()
        {
            _packetParsers.Add(new PacketParser());
            _packetParsers.Add(new CameraStatusReportPacketParser());
        }


        public void Start()
        {
            _tlvUnpacker.Start();
        }

        public void Stop()
        {
            _tlvUnpacker.Stop();
        }

        void _tlvUnpacker_RawPacketReceived(object sender, RawPacketReceivedEventArgs args)
        {
            var processed = false;
            foreach (var packetParser in _packetParsers)
            {
                if (packetParser.CanParse(args.Packet))
                {
                    processed = true;
                    var obj = packetParser.Parse(args.Packet);
                    HandleAck(obj);
                    RaiseNewPacketReceived(new NewPacketEventArgs(obj));
                }

            }

            if (!processed)
            {
                Log("该数据包被丢弃");
            }
        }

        private void HandleAck(object obj)
        {
            if (obj is Packets.LicensePlateInfo)
            {
                var lpi = (Packets.LicensePlateInfo) obj;
                var reply = _lpiReplyPacker.Pack(lpi.PacketId);
                var p = new RawPacket()
                            {
                                IsRequest = false,
                                MessageId = PacketType.LicensePlateInfoAck,
                                Payload = reply
                            };
                _tlvUnpacker.Send(p);
            }
        }

        private void Log(string msg)
        {
            if (_logger != null)
            {
                _logger(msg);
            }
        }
    }
}
